import os
import random
import re

from google.appengine.api import users
from google.appengine.ext import webapp
from google.appengine.ext.webapp import template
from google.appengine.ext.webapp.util import run_wsgi_app
from google.appengine.ext import db


RANDOM_SAMPLE_SIZE = 10 #how many random quotes to pull back and pick one from


###
#  Hold all the data needed for the Quote application
###
class Quote(db.Model):
    text = db.StringProperty()
    first_name = db.StringProperty()
    last_name = db.StringProperty()
    tags = db.StringListProperty()
    randomness = db.IntegerProperty()
    

###
#  RandomQuotePage will find the 10 closest quotes to a random number and
#  then randomly pick one of them to return to index.html
###
class RandomQuotePage(webapp.RequestHandler):
    def get(self):
        random_number = random.randint(0, 99)   #pick out random quotes
        
        quotes_query_gt = Quote.all().order('-randomness')
        quotes_query_lt = Quote.all().order('-randomness')
        
        quotes_query_gt.filter("randomness >=", random_number)
        quotes_query_lt.filter("randomness <", random_number)

        sendQuoteResponse(self, quotes_query_gt, quotes_query_lt, 'index.html')


###
#  RestService will parse a url looking for firstName, lastName, and tag entries
#  An example would be /rest/lastName/Bastiat/firstName/Frederic/tag/money/tag/freedom
###
class RestService(webapp.RequestHandler):
    def get(self):
        url = self.request.url
        
        #to randomly pick a quote look for objects greater than a random number and 
        #if the sample size isn't big enough then fill with quotes found near the
        #random number but smaller
        quotes_query_gt = Quote.all()
        quotes_query_lt = Quote.all()
        
        search = re.search('lastName/(\w+)/?', url)   #look for lastName/ followed by the text for last name
        if search is not None:
            lastName = search.group(1)
            quotes_query_gt.filter("last_name = ", lastName)
            quotes_query_lt.filter("last_name = ", lastName)
            
        search = re.search('firstName/(\w+)/?', url)    #look for firstName/ followed by the text for first name
        if search is not None:
            firstName = search.group(1)
            quotes_query_gt.filter("first_name = ", firstName)
            quotes_query_lt.filter("first_name = ", firstName)
        
        tag_list = re.findall('tag/(\w+)/?', url)   #look for ALL occurrences of tag/ followed by data
            
        if tag_list is not None and (len(tag_list) > 0):
            quotes_query_gt.filter("tags IN ", tag_list)
            quotes_query_lt.filter("tags IN ", tag_list)
            
        random_number = random.randint(0, 99)   #pick out random quotes
        
        quotes_query_gt.order('-randomness')
        quotes_query_lt.order('-randomness')
        
        quotes_query_gt.filter("randomness >=", random_number)
        quotes_query_lt.filter("randomness <", random_number)

        sendQuoteResponse(self, quotes_query_gt, quotes_query_lt, 'rest.html')

       
###
#  sendQuoteResponse is called from RandomQuotePage or RestService with the url to redirect to and
#  a quote to format for display on those pages
###
def sendQuoteResponse(self, quotes_query_gt, quotes_query_lt, html_file):
    quotes = []
        
    quotes_gt = quotes_query_gt.fetch(RANDOM_SAMPLE_SIZE)
    if len(quotes_gt) > 0:  #only add if there were Quotes returned...don't add an empty list to quotes[]
        quotes = quotes_gt[:]
            
    if len(quotes) < RANDOM_SAMPLE_SIZE:  #didn't find enough entries greater than random so try smaller
        quotes_lt = quotes_query_lt.fetch(RANDOM_SAMPLE_SIZE - len(quotes))
        if len(quotes_lt) > 0:  #only add if there were Quotes returned...don't add an empty list to quotes[]
            quotes[len(quotes):] = quotes_lt
                 
    if len(quotes) == 0:  #no quotes in DB so create one
        quote_text = "To err is human; to forgive, divine."
        quote_author = "~Alexander Pope"
    else:   #there was a quote found...randomly select one from the list returned
        quote = quotes[random.randint(0, len(quotes) - 1)]
        quote_text = quote.text
        quote_author = quote.first_name + ' ' + quote.last_name
        if len(quote_author) > 0:
            quote_author = "~" + quote_author.strip()
        
    template_values = {
                       'quote_text': quote_text,
                       'quote_author': quote_author,
                       }

    path = os.path.join(os.path.dirname(__file__), html_file)
    self.response.out.write(template.render(path, template_values))        
        
        
###
#  AdminPage is protected in app.yaml and will return all quotes for admin.html to display
###
class AdminPage(webapp.RequestHandler):
    def get(self):

        quotes_query = Quote.all().order('last_name')
        quotes = quotes_query.fetch(500)

        if users.get_current_user():
            url = users.create_logout_url(self.request.uri)
            url_linktext = 'Logout'
        else:
            url = users.create_login_url(self.request.uri)
            url_linktext = 'Login'

        template_values = {
                           'quotes': quotes,
                           'url' : url,
                           'url_linktext': url_linktext,
                           }

        path = os.path.join(os.path.dirname(__file__), 'admin.html')
        self.response.out.write(template.render(path, template_values))


###
#  AddQuote will parse through data sent from admin.html and add valid quotes
###
class AddQuote(webapp.RequestHandler):
    def post(self):
        text = self.request.get('text') #check if an individual quote was added
        if text is not None and len(text) > 0:
            quote = Quote()
            quote.text = text
            quote.first_name = self.request.get('firstName')
            quote.last_name = self.request.get('lastName')
            tags = self.request.get('tags')
            tags = tags.rsplit()
            quote.tags = tags
            quote.randomness = random.randint(0, 99)
            quote.put()
        
        bulkQuotes = self.request.get('bulkQuotes') #check if any bulk quotes were added
        if bulkQuotes is not None and len(bulkQuotes) > 0:
            lines = bulkQuotes.splitlines()
            if lines is not None:
                for line in lines:
                    input_quote = line.split('|')
                    if input_quote is not None and len(input_quote) >= 3:
                        quote = Quote()
                        quote.text = input_quote[0]
                        quote.first_name = input_quote[1]
                        quote.last_name = input_quote[2]
                        quote.tags = input_quote[3:]
                        quote.randomness = random.randint(0, 99)
                        quote.put()
                                
        self.redirect('/admin')


###
#  DeleteQuote will take the key submitted and delete the quote
###
class DeleteQuote(webapp.RequestHandler):
    def post(self):
        quote_key = self.request.get('quoteKey')
        db.delete(quote_key)
            
        self.redirect('/admin')
 

###
#  Which URLs are handled by this application
###
application = webapp.WSGIApplication(
                                     [('/', RandomQuotePage),
                                      ('/admin', AdminPage),
                                      ('/admin/addQuote', AddQuote), 
                                      ('/admin/deleteQuote', DeleteQuote),
                                      ('/rest.*', RestService)],
                                     debug=False)


###
#  Run the application
###
def main():
    run_wsgi_app(application)


###
#  Call the main function
###
if __name__ == "__main__":
    main()